home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / faq / wdj0597.zip / SDKANN.ZIP / SOURCE.ZIP / CHEKLIST.C < prev    next >
C/C++ Source or Header  |  1997-01-09  |  10KB  |  318 lines

  1. /*****************************************************/
  2. /* cheklist.c                                        */
  3. /* -- Listbox subclass uses user supplied bitmap to  */
  4. /*    show selection.                                */
  5. /* -- Make with:                                     */
  6. /*    cc -wd -DSTRICT cheklist.c                     */
  7. /*    copy cheklist.dll cheklist.exe                 */
  8. /*****************************************************/
  9.  
  10. #define OEMRESOURCE
  11. #include <windows.h>
  12. #include <windowsx.h>
  13. #include <assert.h>
  14.  
  15. #define max(a,b) ((a)>(b)?(a):(b))
  16.  
  17.  
  18. WNDPROC lpfnOrig; /* Original list box wnd proc. */
  19. char    szMod[] = "ChekList"; /* Module name. */
  20. char    szFuncLo[] = "ChekListLo"; /* Property tags. */
  21. char    szFuncHi[] = "ChekListHi";
  22.  
  23. /* Prototypes. */
  24. void    DrawCheck(LPDRAWITEMSTRUCT, LPBITMAP, HBITMAP);
  25. void    DrawListItem(LPDRAWITEMSTRUCT);
  26. void    DrawString(LPDRAWITEMSTRUCT, LPBITMAP);
  27. HWND    HwndGetList(HWND, UINT, UINT);
  28.  
  29. /* Callbacks. */
  30. LRESULT CALLBACK __export
  31.     LwParentProc(HWND, UINT, WPARAM, LPARAM);
  32. LRESULT CALLBACK __export
  33.     LwListProc(HWND, UINT, WPARAM, LPARAM);
  34.  
  35. int    InitCheckList(HINSTANCE hins)
  36. /*****************************************************/
  37. /* -- Initialization entry point.                    */
  38. /* -- Register the "ChekList" class.                 */
  39. /*****************************************************/
  40.     {
  41.     WNDCLASS    wcs;
  42.  
  43.     GetClassInfo(NULL, "ListBox", &wcs);
  44. //    wcs.style |= CS_GLOBALCLASS;
  45.     wcs.lpszClassName = szMod;
  46.     wcs.hInstance = hins;
  47.     lpfnOrig = wcs.lpfnWndProc;
  48.     wcs.lpfnWndProc = LwListProc;
  49.     return RegisterClass(&wcs);
  50.     }
  51.  
  52. LRESULT CALLBACK __export LwListProc(HWND hwnd,
  53.   UINT wm, WPARAM wParam, LPARAM lParam)
  54. /*****************************************************/
  55. /* Listbox window procedure.                         */
  56. /*****************************************************/
  57.     {
  58.     switch (wm)
  59.         {
  60.     default:
  61.         break;
  62.  
  63.     case WM_CREATE: /* Subclass parent to intercept */
  64.         {           /* owner draw messages. */
  65.         LPCREATESTRUCT  lpcrs = (LPCREATESTRUCT)lParam;
  66.         HWND            hwndParent = lpcrs->hwndParent;
  67.         LONG            lpfn;
  68.  
  69.         if (GetProp(hwndParent, szFuncLo) == NULL)
  70.             {
  71.             lpfn = GetWindowLong(hwndParent,
  72.               GWL_WNDPROC);
  73.             SetProp(hwndParent, szFuncLo,
  74.               (HANDLE)LOWORD(lpfn));
  75.             SetProp(hwndParent, szFuncHi,
  76.               (HANDLE)HIWORD(lpfn));
  77.             SubclassWindow(hwndParent, LwParentProc);
  78.             }
  79.  
  80.         /* Store bitmap to draw. */
  81.         SetProp(hwnd, szMod,
  82.           (HANDLE)(LONG)LoadBitmap(NULL, (LPCSTR)OBM_CHECK));
  83.         }
  84.         break;
  85.  
  86.     case WM_DESTROY:
  87.         DeleteObject(RemoveProp(hwnd, szMod));
  88.         break;
  89.         }   /* End switch wm. */
  90.  
  91.     return CallWindowProc(lpfnOrig, hwnd, wm, wParam,
  92.       lParam);
  93.     }
  94.  
  95. LRESULT CALLBACK __export LwParentProc(HWND hwnd,
  96.   UINT wm, WPARAM wParam, LPARAM lParam)
  97. /*****************************************************/
  98. /* -- Listbox parent subclass procedure.             */
  99. /*****************************************************/
  100.     {
  101.     WNDPROC lpfn;
  102.  
  103.     lpfn = (WNDPROC)MAKELONG(GetProp(hwnd, szFuncLo),
  104.       GetProp(hwnd, szFuncHi));
  105.  
  106.     switch (wm)
  107.         {
  108.     default:
  109.         break;
  110.  
  111.     case WM_DESTROY:    /* Remove subclasser. */
  112.         RemoveProp(hwnd, szFuncLo);
  113.         RemoveProp(hwnd, szFuncHi);
  114.         SubclassWindow(hwnd, lpfn);
  115.         break;
  116.  
  117.     case WM_MEASUREITEM:
  118.         {
  119.         LPMEASUREITEMSTRUCT lpmis;
  120.         HDC                 hdc;
  121.         HWND                hwndList;
  122.  
  123.         /* Is it for us? */
  124.         lpmis = (LPMEASUREITEMSTRUCT)lParam;
  125.         if ((hwndList = HwndGetList(hwnd,
  126.           lpmis->CtlType, lpmis->CtlID)) == NULL)
  127.             break;  /* Nope. */
  128.  
  129.         if ((hdc = GetDC(hwndList)) != NULL)
  130.             {
  131.             TEXTMETRIC  txm;
  132.             BITMAP      bmp;
  133.             HBITMAP     hbmp;
  134.  
  135.             /* Leave 2 border thicknesses for caret. */
  136.             if ((hbmp = (HBITMAP)GetProp(hwndList, szMod)) !=
  137.               NULL)
  138.                 { 
  139.                 GetObject(hbmp, sizeof bmp, &bmp);
  140.                 GetTextMetrics(hdc, &txm);
  141.                 lpmis->itemHeight =
  142.                   max(txm.tmHeight, bmp.bmHeight) +
  143.                   2 * GetSystemMetrics(SM_CYBORDER)
  144.                   - 4 /* ??? ron slop ??? */;
  145.                 }
  146.             ReleaseDC(hwndList, hdc);
  147.             }
  148.         }
  149.         return TRUE;
  150.  
  151.     case WM_DRAWITEM:
  152.         {
  153.         LPDRAWITEMSTRUCT    lpdis;
  154.  
  155.         /* Is it for us? */
  156.         lpdis = (LPDRAWITEMSTRUCT)lParam;
  157.         if (HwndGetList(hwnd, lpdis->CtlType,
  158.           lpdis->CtlID) == NULL)
  159.             break;  /* Nope. */
  160.         DrawListItem(lpdis);
  161.         }
  162.         return TRUE;
  163.         }
  164.  
  165.     return CallWindowProc(lpfn, hwnd, wm, wParam,
  166.       lParam);
  167.     }
  168.  
  169. HWND HwndGetList(HWND hwndParent, UINT wType, UINT did)
  170. /*****************************************************/
  171. /* -- Determine if the control is a ChekList.        */
  172. /* -- Return window handle if so, else NULL.         */
  173. /*****************************************************/
  174.     {
  175.     HWND    hwnd;
  176.     char    szBuf[sizeof szMod];
  177.  
  178.     if (wType != ODT_LISTBOX ||
  179.       (hwnd = GetDlgItem(hwndParent, did)) == NULL)
  180.         return NULL;
  181.     GetClassName(hwnd, szBuf, sizeof szBuf);
  182.     return lstrcmp(szBuf, szMod) == 0 ? hwnd : NULL;
  183.     }
  184.  
  185. void DrawListItem(LPDRAWITEMSTRUCT lpdis)
  186. /*****************************************************/
  187. /* -- Draw an entry in the list box.                 */
  188. /*****************************************************/
  189.     {
  190.     HBITMAP hbmp =0;
  191.     BITMAP  bmp;
  192.  
  193.     if (lpdis->itemAction != ODA_FOCUS)
  194.         {
  195.         if ((hbmp = (HBITMAP)GetProp(lpdis->hwndItem, szMod)) ==
  196.           NULL)
  197.             return; /* Out of GDI memory. */
  198.         GetObject(hbmp, sizeof bmp, &bmp);
  199.         }
  200.     if(lpdis->itemAction & ODA_DRAWENTIRE)
  201.         {
  202.         DrawCheck(lpdis, &bmp, hbmp);
  203.         DrawString(lpdis, &bmp);
  204.         }
  205.     if(lpdis->itemAction & ODA_FOCUS)
  206.         {
  207.         DrawFocusRect(lpdis->hDC, &lpdis->rcItem);
  208.         }
  209.     if(lpdis->itemAction & ODA_SELECT)
  210.         {
  211.         DrawCheck(lpdis, &bmp, hbmp);
  212.         DrawString(lpdis, &bmp);
  213.         }
  214. #if 0
  215.     switch (lpdis->itemAction)
  216.         {
  217.     default:
  218.         assert(FALSE);
  219.         break;  /* Should assert. */
  220.  
  221.     case ODA_DRAWENTIRE:
  222.         DrawCheck(lpdis, &bmp, hbmp);
  223.         DrawString(lpdis, &bmp);
  224.         if (!(lpdis->itemState & ODS_FOCUS))
  225.             break;  /* Otherwise, fall through. */
  226.  
  227.     case ODA_FOCUS:
  228.         DrawFocusRect(lpdis->hDC, &lpdis->rcItem);
  229.         break;
  230.  
  231.     case ODA_SELECT:
  232.         DrawCheck(lpdis, &bmp, hbmp);
  233.         DrawString(lpdis, &bmp);
  234.         break;
  235.         }
  236. #endif
  237.  
  238.     }
  239.  
  240. void DrawString(LPDRAWITEMSTRUCT lpdis, LPBITMAP lpbmp)
  241. /*****************************************************/
  242. /* -- Draw a string in the list box.                 */
  243. /*****************************************************/
  244.     {
  245.     int     cb;
  246.     LPSTR    lpsz;
  247.  
  248.     cb = (int)SendMessage(lpdis->hwndItem,
  249.       LB_GETTEXTLEN, lpdis->itemID, 0);
  250.  
  251.     if ((lpsz = (LPSTR)GlobalAllocPtr(GHND, cb+1)) == NULL)
  252.         return; /* No memory for string. */
  253.     SendMessage(lpdis->hwndItem,
  254.       LB_GETTEXT, lpdis->itemID, (LONG)lpsz);
  255.  
  256.     COLORREF OldText, OldBk;
  257.  
  258.     if ((lpdis->itemState & ODS_SELECTED))
  259.         {
  260.         OldText = SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  261.         OldBk   = SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
  262.         }
  263.     else
  264.         {
  265.         OldText = SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
  266.         OldBk   = SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
  267.         }
  268.  
  269. int aTabs[2] = { 50, 75 };
  270.  
  271. TabbedTextOut(lpdis->hDC,               /* handle of device context   */
  272.     lpdis->rcItem.left + (lpbmp->bmWidth * 2),
  273.     lpdis->rcItem.top + 1,
  274.     lpsz,              /* address of text            */
  275.     lstrlen(lpsz),     /* number of characters       */
  276.     sizeof(aTabs) / sizeof(int), /* number of tabs in array    */
  277.     aTabs,                       /* array for tab positions    */
  278.     0);                 /* x-coord. for tab expanding */
  279.  
  280.  
  281.     SetTextColor(lpdis->hDC, OldText);
  282.     SetBkColor(lpdis->hDC, OldBk);
  283.     GlobalFreePtr(lpsz);
  284.     }
  285.  
  286. void DrawCheck(LPDRAWITEMSTRUCT lpdis, LPBITMAP lpbmp, HBITMAP hbmp)
  287. /*****************************************************/
  288. /* -- Draw a check mark in the list box.             */
  289. /*****************************************************/
  290.     {
  291.     HDC     hdcMem;
  292.     HBITMAP hbmpSav;
  293.  
  294.     PatBlt(lpdis->hDC, lpdis->rcItem.left,
  295.       lpdis->rcItem.top, lpbmp->bmWidth * 2,
  296.       lpdis->rcItem.bottom - lpdis->rcItem.top,
  297.       WHITENESS); /* Erase. */
  298.     if (!(lpdis->itemData & 0x8000))
  299.         return; /* Nothing more to draw. */
  300.  
  301.  
  302.     if ((hdcMem = CreateCompatibleDC(lpdis->hDC)) ==
  303.       NULL)
  304.         return; /* Out of GDI memory. */
  305.  
  306.     if ((hbmpSav = (HBITMAP)SelectObject(hdcMem, hbmp)) != NULL)
  307.         {
  308.         BitBlt(lpdis->hDC,
  309.           lpdis->rcItem.left + lpbmp->bmWidth / 2,
  310.           ((lpdis->rcItem.bottom + lpdis->rcItem.top) -
  311.             lpbmp->bmHeight) / 2, lpbmp->bmWidth,
  312.           lpbmp->bmHeight, hdcMem, 0, 0, SRCCOPY);
  313.         SelectObject(hdcMem, hbmpSav);
  314.         }
  315.  
  316.     DeleteDC(hdcMem);
  317.     }
  318.